{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model I/O - Prompt ExampleSelector 少样本提示，示例选择器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## LengthBasedExampleSelector 按长度示例选择器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Give the antonym of every input\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: big\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "from langchain.prompts.example_selector import LengthBasedExampleSelector\n",
    "\n",
    "# 示例列表。\n",
    "examples = [\n",
    "    {\"input\": \"happy\", \"output\": \"sad\"},\n",
    "    {\"input\": \"tall\", \"output\": \"short\"},\n",
    "    {\"input\": \"energetic\", \"output\": \"lethargic\"},\n",
    "    {\"input\": \"sunny\", \"output\": \"gloomy\"},\n",
    "    {\"input\": \"windy\", \"output\": \"calm\"},\n",
    "]\n",
    "\n",
    "\n",
    "# 定义如何将示例数据格式化为字符串的模板。\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"input\", \"output\"],\n",
    "    template=\"Input: {input}\\nOutput: {output}\",\n",
    ")\n",
    "\n",
    "# 使用LengthBasedExampleSelector选择符合长度要求的示例。\n",
    "example_selector = LengthBasedExampleSelector(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    # 设置长度。\n",
    "    max_length=8,\n",
    ")\n",
    "\n",
    "# 创建FewShotPromptTemplate，动态地根据输入选择示例并生成提示。\n",
    "dynamic_prompt = FewShotPromptTemplate(\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "    prefix=\"Give the antonym of every input\",\n",
    "    suffix=\"Input: {adjective}\\nOutput:\",\n",
    "    input_variables=[\"adjective\"],\n",
    ")\n",
    "\n",
    "\n",
    "print(dynamic_prompt.format(adjective=\"big\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MaxMarginalRelevanceExampleSelector 基于最大边际相关性的示例选择器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "安装向量数据库FAISS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install faiss-cpu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "引入类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "from langchain.prompts.example_selector import MaxMarginalRelevanceExampleSelector\n",
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_community.embeddings.openai import OpenAIEmbeddings\n",
    "\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sk-B9B9sfxkQXtgDEAU4bkg4Iw4pwdW4budAOFVjHL8Je44foLk\n",
      "https://api.fe8.cn/v1\n",
      "Give the antonym of every input\n",
      "\n",
      "Input: happy\n",
      "Output: sad\n",
      "\n",
      "Input: windy\n",
      "Output: calm\n",
      "\n",
      "Input: worried\n",
      "Output:\n"
     ]
    }
   ],
   "source": [
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"input\", \"output\"],\n",
    "    template=\"Input: {input}\\nOutput: {output}\",\n",
    ")\n",
    "\n",
    "# 创建反义词任务的示例\n",
    "examples = [\n",
    "    {\"input\": \"happy\", \"output\": \"sad\"},\n",
    "    {\"input\": \"tall\", \"output\": \"short\"},\n",
    "    {\"input\": \"energetic\", \"output\": \"lethargic\"},\n",
    "    {\"input\": \"sunny\", \"output\": \"gloomy\"},\n",
    "    {\"input\": \"windy\", \"output\": \"calm\"},\n",
    "]\n",
    "\n",
    "# 配置 OpenAI 服务\n",
    "OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')  ## 设置openai的key\n",
    "OPENAI_API_BASE = os.getenv('OPENAI_BASE_URL')  ## 更换为代理地址\n",
    "print(os.getenv(\"OPENAI_API_KEY\"))\n",
    "print(os.getenv(\"OPENAI_BASE_URL\"))\n",
    "\n",
    "example_selector = MaxMarginalRelevanceExampleSelector.from_examples(\n",
    "    # 可供选择的示例列表\n",
    "    examples,\n",
    "    # 用于生成语义相似性嵌入的嵌入类\n",
    "    OpenAIEmbeddings(openai_api_base=OPENAI_API_BASE, openai_api_key=OPENAI_API_KEY),\n",
    "    # 用于存储嵌入并进行相似性搜索的VectorStore类\n",
    "    FAISS,\n",
    "    # 要生成的示例数量\n",
    "    k=2,\n",
    ")\n",
    "\n",
    "mmr_prompt = FewShotPromptTemplate(\n",
    "    # 我们提供一个示例选择器，而不是示例\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "     prefix=\"Give the antonym of every input\",\n",
    "    suffix=\"Input: {adjective}\\nOutput:\",\n",
    "    input_variables=[\"adjective\"],\n",
    ")\n",
    "\n",
    "# 如果输入是一个情感或属性，应该首先选择相关的示例\n",
    "print(mmr_prompt.format(adjective=\"worried\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SemanticSimilarityExampleSelector 基于相关性的示例选择器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "引入类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_community.embeddings.openai import OpenAIEmbeddings\n",
    "\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"input\", \"output\"],\n",
    "    template=\"输入: {input}\\n输出: {output}\",\n",
    ")\n",
    "\n",
    "# 创建反义词任务的示例\n",
    "examples = [\n",
    "    {\"input\": \"黑暗\", \"output\": \"光明\"},\n",
    "    {\"input\": \"寒冷\", \"output\": \"温暖\"},\n",
    "    {\"input\": \"干燥\", \"output\": \"湿润\"},\n",
    "    {\"input\": \"安静\", \"output\": \"喧闹\"},\n",
    "    {\"input\": \"平滑\", \"output\": \"粗糙\"},\n",
    "]\n",
    "\n",
    "# 配置 OpenAI 服务\n",
    "OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')  ## 设置openai的key\n",
    "OPENAI_API_BASE = os.getenv('OPENAI_BASE_URL')  ## 更换为代理地址\n",
    "print(os.getenv(\"OPENAI_API_KEY\"))\n",
    "print(os.getenv(\"OPENAI_BASE_URL\"))\n",
    "\n",
    "example_selector = SemanticSimilarityExampleSelector.from_examples(\n",
    "    # 可供选择的示例列表\n",
    "    examples,\n",
    "    # 用于生成语义相似性嵌入的嵌入类\n",
    "    OpenAIEmbeddings(openai_api_base=OPENAI_API_BASE, openai_api_key=OPENAI_API_KEY),\n",
    "    # 用于存储嵌入并进行相似性搜索的VectorStore类\n",
    "    FAISS,\n",
    "    # 要生成的示例数量\n",
    "    k=2,\n",
    ")\n",
    "\n",
    "mmr_prompt = FewShotPromptTemplate(\n",
    "    # 我们提供一个示例选择器，而不是示例\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "    prefix=\"给出每个输入的反义词\",\n",
    "    suffix=\"输入: {adjective}\\n输出:\",\n",
    "    input_variables=[\"adjective\"],\n",
    ")\n",
    "\n",
    "# 如果输入是一个情感或属性，应该首先选择相关的示例\n",
    "print(mmr_prompt.format(adjective=\"快乐\"))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NGramOverlapExampleSelector 按词语重叠度示例选择器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import FewShotPromptTemplate, PromptTemplate\n",
    "from langchain.prompts.example_selector.ngram_overlap import NGramOverlapExampleSelector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 示例 prompt 模版\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"input\", \"output\"],\n",
    "    template=\"输入: {input}\\n输出: {output}\",\n",
    ")\n",
    "\n",
    "# 示例列表\n",
    "examples = [\n",
    "    {\"input\": \"See Spot run.\", \"output\": \"Ver correr a Spot.\"},\n",
    "    {\"input\": \"My dog barks.\", \"output\": \"Mi perro ladra.\"},\n",
    "    {\"input\": \"Spot can run.\", \"output\": \"Spot puede correr.\"},\n",
    "]\n",
    "\n",
    "example_selector = NGramOverlapExampleSelector(\n",
    "    # 示例列表。\n",
    "    examples=examples,\n",
    "    # 用于格式化示例的PromptTemplate。\n",
    "    example_prompt=example_prompt,\n",
    "    # 词语重叠度，0.0-1.0区间\n",
    "    threshold=0.0,\n",
    ")\n",
    "\n",
    "dynamic_prompt = FewShotPromptTemplate(\n",
    "    # 我们提供一个ExampleSelector而不是示例。\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "    prefix=\"将输入的英语翻译成西班牙语\",\n",
    "    suffix=\"输入: {sentence}\\n输出:\",\n",
    "    input_variables=[\"sentence\"],\n",
    ")\n",
    "\n",
    "print(dynamic_prompt.format(sentence=\"Spot can run fast.\"))\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
